home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / rexx / imc / rexx-imc.5 / rxque.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-25  |  8.4 KB  |  223 lines

  1. /* The stack server of REXX/imc                    (C) Ian Collier 1992 */
  2.  
  3. #include<sys/types.h>
  4. #include<errno.h>
  5. #include<signal.h>
  6. #include<fcntl.h>
  7. #include<sys/wait.h>
  8. #include<sys/socket.h>
  9. #include<sys/time.h>
  10. #include<sys/stat.h>
  11. #include<stdio.h>
  12. #include<malloc.h>
  13.  
  14. int io();                            /* function which does the work */
  15. void term();                         /* cleanup function */
  16.  
  17. struct {u_short af;char name[100];}  /* a mimic of struct sockaddr, but */
  18.        sock={AF_UNIX};               /* with a longer name field. */
  19. int socklen;                         /* The length of the socket name */
  20. int sockfds=0;                       /* Collection of bits for fds in use */
  21. int s;                               /* Socket fd */
  22. char inbuf[20];                      /* for reading into */
  23. char *sname;                         /* Socket file name */
  24. static char uname[100];              /* for storing the socket file name */
  25. char dname[100];             /* for storing the socket directory */
  26. char **stack;                        /* Pointer to the stack structure */
  27. int first,last;                      /* First and last elements in circle */
  28. int empty;                           /* Is stack empty when first==last? */
  29. unsigned max;                        /* Number of stack elements allocated */
  30.  
  31. main(argc,argv)           /* Specify "-csh" and/or a filename */
  32. int argc;
  33. char **argv;
  34. {
  35.    int t;
  36.    int csh=0;
  37.    int parent=getppid();
  38.    if(argc>1&&!strcmp(argv[1],"-csh"))argv++,argc--,csh++;
  39.    if(argc>2)fputs("Usage: rxque [-csh] [socketname]\n",stderr),exit(1);
  40.    umask(077);
  41.    if(argc==2)sname=argv[1];  /* must be the supplied file name */
  42.    else{                      /* make one up */
  43.       sprintf(dname,"/tmp/rxsock%d",getuid()),
  44.       sprintf(uname,"%s/rxstack.%d",dname,getpid());
  45.       if(mkdir(dname,0700)&&errno!=EEXIST)
  46.          perror("Cannot create socket directory"),
  47.          exit(1);
  48.       sname=uname;
  49.    }
  50.    unlink(sname);             /* just in case it was there already */
  51.    strcpy(sock.name,sname);
  52.    socklen=sizeof(u_short)+strlen(sname);
  53.    s=socket(AF_UNIX,SOCK_STREAM,0);
  54.    if(s<0)perror("Cannot create socket"),exit(1);
  55.    if(bind(s,&sock,socklen)<0)perror("Error in bind call"),exit(1);
  56.    if(listen(s,1)<0)perror("Error in listen call"),exit(1);
  57.    setpgrp(0,getpid());       /* Prevent signals from keyboard */
  58.    if((t=fork())<0)perror("fork"),exit(1);
  59.    if(t){                     /* Parent: output data and exit */
  60.       if(argc==2)printf("%d\n",t);
  61.       else
  62.          if(csh)printf("setenv RXSTACK %s;setenv RXSTACKPROC %d",sname,t);
  63.          else printf("RXSTACK=%s RXSTACKPROC=%d",sname,t);
  64.       fflush(stdout),
  65.       exit(0);
  66.    }
  67.    /* Child: now in background, so start serving */
  68.    if(!(stack=(char**)malloc((max=128)*sizeof(char*))))
  69.       perror("malloc"),exit(1);
  70.    fclose(stdout),fclose(stdin),
  71.    freopen("/dev/tty","w",stderr); /* In case of error messages */
  72.    signal(SIGTERM,term);           /* enable cleanup when killed */
  73.    first=0;last=0;empty=1;
  74.    while(1)
  75.       if(!io()){                   /* returns 0 if inactive for 5 minutes */
  76.          if(kill(parent,0)&&errno==ESRCH)
  77.         fputs("RX Stack: Exiting since parent no longer exists\n",stderr),
  78.         fflush(stderr),
  79.         term();
  80.       }
  81. }
  82.  
  83. int io() /* Wait for connections; return 0 if timed out, 1 otherwise */
  84. {
  85.    int sfd1=1<<s;              /* bit for socket fd */
  86.    int readfds=sockfds|sfd1;   /* bits for all fds including socket */
  87.    int nfds;
  88.    int sfd=sfd1;
  89.    int t;
  90.    int rc;
  91.    int len;
  92.    int rdlen;
  93.    int i;
  94.    char c;
  95.    char *mem;
  96.    struct timeval timeout;
  97.    timeout.tv_sec=300;timeout.tv_usec=0;  /* 5 minute timeout */
  98.    if(!(nfds=select(32,&readfds,0,&sfd,&timeout)))return 0;
  99.    if(nfds<0)return 1; /* Error (what to do?) */
  100.    if(sfd||(readfds&sfd1)){ /* The socket is ready for action */
  101.       if((t=accept(s,&sock,&socklen))<0); /* Error (what to do?) */
  102.       else sockfds|=(1<<t);
  103.    }
  104.    readfds&= ~sfd1;  /* Exclude the socket's bit */
  105.    t=1,sfd=0;        /* Initialise fd=0, bit=1 */
  106.    while(readfds){   /* Process all fds which are available for read */
  107.       if(t&readfds){ /* Test each one in turn */
  108.          rc=read(sfd,inbuf,1);          /* Get the command character */
  109.          if(rc>0)switch(inbuf[0]){      /* and select appropriate action */
  110.             case 'N':len=last-first;    /* Num: output last-first (mod max) */
  111.                if(len<=0&&!empty)len+=max;
  112.                sprintf(inbuf,"%06X\n",len);
  113.                if(write(sfd,inbuf,7)<7)rc=-1;
  114.                break;
  115.             case 'S':                   /* Stack */
  116.             case 'Q':                   /* Queue */
  117.               if(read(sfd,inbuf+1,7)<7){ /* Get the data length */
  118.                   rc=-1;
  119.                   break;
  120.                }
  121.                for(len=0,i=1;i<7;i++){       /* Interpret the hex value */
  122.                   len<<=4;
  123.                   if((c=inbuf[i])>='0'&&c<='9')len+=c-'0';
  124.                   else if(c>='A'&&c<='F')len+=c-'A'+10;
  125.                   else if(c>='a'&&c<='f')len+=c-'a'+10;
  126.                   else rc=-1;
  127.                }
  128.                if(rc<0)break;
  129.                if(first==last&&!empty){     /* Extend the full stack */
  130.                   if(!(stack=(char**)realloc((char *)stack,(max<<=1)*sizeof(char *))))
  131.                      perror("RX Stack server: Unable to allocate memory"),
  132.                      exit(1);
  133.                   memcpy((char *)(stack+first+max/2),(char *)(stack+first),(max/2-first)*sizeof(char*));
  134.                   first+=max/2;
  135.                }              /* next allocate memory for a stack entry */
  136.                if(!(mem=malloc((unsigned)len+sizeof(int)))){
  137.                   rc=-1;
  138.                   perror("RX Stack server: Unable to stack data");
  139.                   break;
  140.                }
  141.            rdlen=0;
  142.            while(rdlen<len&&rc>0)       /* Read the data to be stacked */
  143.                   if((i=read(sfd,mem+sizeof(int)+rdlen,len-rdlen))<1)rc=-1;
  144.           else rdlen+=i;
  145.                if(rc>0) {
  146.                   *(int *)mem=len;          /* Store its length */
  147.                   empty=0;
  148.                   if(inbuf[0]=='Q'){        /* Put its address in the array */
  149.                      stack[last++]=mem;
  150.                      if(last==max)last=0;
  151.                   }
  152.                   else{
  153.                      if(--first<0)first+=max;
  154.                      stack[first]=mem;
  155.                   }
  156.                }
  157.                break;
  158.             case 'G':                   /* Get */
  159.             case 'P':if(empty){         /* Peek */
  160.                   if(write(sfd,"FFFFFF\n",7)<7)rc=-1;
  161.                   break;
  162.                }
  163.                sprintf(inbuf+1,"%06X\n",len=*(int *)stack[first]);
  164.                if(write(sfd,inbuf+1,7)<7)rc=-1;  /* Write the data */
  165.                else if(write(sfd,stack[first]+sizeof(int),len)<len)rc=-1;
  166.                if(inbuf[0]=='P')break;           /* Continue if it was "Get" */
  167.             case 'D':if(empty)break;    /* Drop */
  168.            free(stack[first]);
  169.                if(++first==max)first=0;
  170.                if(first==last)empty=1;
  171.             break;
  172.             case 'K':                   /* Kill me */
  173.               if(read(sfd,inbuf+1,8)<8){ /* Get the pid and signal */
  174.                   rc=-1;
  175.                   break;
  176.                }
  177.                for(len=0,i=1;i<7;i++){       /* Interpret the hex value */
  178.                   len<<=4;
  179.                   if((c=inbuf[i])>='0'&&c<='9')len+=c-'0';
  180.                   else if(c>='A'&&c<='F')len+=c-'A'+10;
  181.                   else if(c>='a'&&c<='f')len+=c-'a'+10;
  182.                   else rc=-1;
  183.                }
  184.                if(rc<0)break;
  185.            kill(len,inbuf[8]);
  186.            break;
  187.             default:rc=-1;             /* Unrecognised */
  188.          }
  189.          if(rc<=0)close(sfd),sockfds&= ~t; /* Error: close connection */
  190.          readfds&= ~t;
  191.       }
  192.       t<<=1;  /* Move to the next fd */
  193.       sfd++;
  194.    }
  195.    return 1;
  196. }
  197.  
  198. void term(){
  199.    int n;
  200.    int l;
  201.    char *p,*q;
  202.    close(s);      /* Close and remove the socket */
  203.    unlink(sname);
  204.    if(!empty){    /* Print and free all stacked items */
  205.       n=last-first;
  206.       if(n<0)n+=max;
  207.       fprintf(stderr,"RX Stack: %d item%s still stacked\n",n,n==1?"":"s");
  208.       while(n-->0){
  209.          fputc('>',stderr);
  210.          q=p=stack[first++];
  211.          if(first==max)first=0;
  212.          l=*(int *)p;
  213.          p+=sizeof(int);
  214.          while(l--)fputc(*p>=' '&&*p<=0x7e?*p:'?',stderr),p++;
  215.          fputc('\n',stderr);
  216.          free(q);
  217.       }
  218.       fflush(stderr);
  219.    }
  220.    free((char *)stack);
  221.    exit(0);
  222. }
  223.